﻿//////////////////////////////////////////////////////////////////
//
// Archive.cs
//
// Copyright (c) 2012 Dan Pike. All rights reserved
//
// Refer to license.txt for any license restrictions.
// 
using Logger4Net;
using Utilities;
using System.Configuration;
using System.IO;

namespace Utilities
{
   public class Archive : ConfigurationSection
   {
      ////////////////////////////////////////////////////////////////////////
      //
      protected Archive()
      {
         properties_ = new ConfigurationPropertyCollection();
      }

      ////////////////////////////////////////////////////////////////////////
      //
      protected override ConfigurationPropertyCollection Properties
      {
         get { return properties_; }
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public static T create<T>(string section) where T : Archive, new()
      {
         return create<T>(section, null);
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public static T create<T>(string sectionName, string filename) where T : Archive, new()
      {
         T archive = null;
         try
         {
            Configuration config;
            if (!string.IsNullOrWhiteSpace(filename))
            {
               logger_.debugFormat("loading {0} archive from '{1}'", sectionName, filename);
               ExeConfigurationFileMap archiveFileMap = new ExeConfigurationFileMap();
               archiveFileMap.ExeConfigFilename = filename;

               config = ConfigurationManager.OpenMappedExeConfiguration(archiveFileMap, ConfigurationUserLevel.None);
            }
            else
            {
               // Default config file for the application
               logger_.debugFormat("loading {0} archive from executing assembly", sectionName);
               config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            }
            archive = config.GetSection(sectionName) as T;
            if (null == archive)
            {
               archive = new T();
               config.Sections.Add(sectionName, archive);
            }
            (archive as T).config_ = config;
            archive.sectionName_ = sectionName;
         }
         catch (System.Exception ex)
         {
            logger_.exception(ex);
            archive = null;
         }
         return archive;
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public bool save()
      {
         try
         {
            config_.Save(ConfigurationSaveMode.Full);
            return true;
         }
         catch (System.Exception ex)
         {
            logger_.exception("{0}.save()", ex, sectionName_);
         }
         return false;
      }

      ////////////////////////////////////////////////////////////////////////
      //
      public bool saveAs(string sectionName, string filename)
      {
         try
         {
            logger_.debugFormat("saving {0} to '{1}'", sectionName, filename ?? "executing assembly");
            if (!string.IsNullOrWhiteSpace(filename) && (null != config_) &&
               (Path.GetFullPath(filename) == Path.GetFullPath(config_.FilePath)))
            {
               config_.Save(ConfigurationSaveMode.Full);
            }
            else
            {
               config_.SaveAs(filename, ConfigurationSaveMode.Full);
            }
            return true;
         }
         catch (System.Exception ex)
         {
            string effectiveFile = (null != config_) ? string.Concat("opened:", config_.FilePath) : null;
            effectiveFile = effectiveFile ?? string.Concat("supplied:", filename);
            effectiveFile = effectiveFile ?? string.Empty;
            logger_.exception("{0}.saveAs({1})", ex, sectionName, effectiveFile);
         }
         return false;
      }

      ////////////////////////////////////////////////////////////////////////
      //
      protected static Logger logger_ = new Logger(typeof(Archive));
      private ConfigurationPropertyCollection properties_;
      private Configuration config_;
      private string sectionName_ = string.Empty;
   }
}
